using Microsoft.Extensions.DependencyInjection;

namespace Crux.Core.EasyNetQ;
/// <summary>
/// ServiceProviderSubscriberMessageDispatcher
/// </summary>
public class ServiceProviderSubscriberMessageDispatcher(
    IServiceProvider serviceProvider,
    ILogger<ServiceProviderSubscriberMessageDispatcher> logger)
    : IAutoSubscriberMessageDispatcher
{
    #region private fields
    private readonly IServiceProvider _provider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
    private readonly ILogger<ServiceProviderSubscriberMessageDispatcher> _logger = logger ?? throw new ArgumentNullException(nameof(logger));
    #endregion  private fields

    #region implements IAutoSubscriberMessageDispatcher
    /// <inheritdoc/>
    public void Dispatch<TMessage, TConsumer>(
        TMessage message,
        CancellationToken cancellationToken)
        where TMessage : class where TConsumer : class, IConsume<TMessage>
    {
        using var scope = _provider.CreateScope();

        _logger.LogInformation($"handle message:{typeof(TMessage)}");

        try
        {
            var consumer = scope.ServiceProvider.GetRequiredService<TConsumer>();

            consumer.Consume(message, cancellationToken);
            _logger.LogInformation($"handled message:{typeof(TMessage)}");
        }
        catch (Exception e)
        {
            _logger.LogError(e, e.Message);
            throw;
        }
    }

    /// <inheritdoc/>
    public async Task DispatchAsync<TMessage, TConsumer>(TMessage message, CancellationToken cancellationToken)
         where TMessage : class where TConsumer : class, IConsumeAsync<TMessage>
    {
        await using var scope = _provider.CreateAsyncScope();

        _logger.LogInformation($"handle message:{typeof(TMessage)}");

        try
        {
            var consumer = scope.ServiceProvider.GetRequiredService<TConsumer>();

            await consumer.ConsumeAsync(message, cancellationToken).ConfigureAwait(false);

            _logger.LogInformation($"handled message:{typeof(TMessage)}");
        }
        catch (Exception e)
        {
            _logger.LogError(e, e.Message);
            throw;
        }
    }
    #endregion implements IAutoSubscriberMessageDispatcher
}